package application.chat;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.SocketException;
import java.util.Date;

import GUI.ChatGUI;
import application.*;

public class Chat extends Thread implements Application {
	private ControlConnectionToTransport controlConnection;
	private DataConnectionToTransport dataConnection;
	private String name;
	private BufferedReader in;
	private BufferedWriter out;
	private boolean connected;
	private ChatGUI gui;

	/**
	 * Makes a new chat application it also sets the control connection
	 * 
	 * @param name
	 */
	public Chat(String name, ChatGUI gui) {
		connected = false;
		this.name = name;
		this.gui = gui;
		try {
			controlConnection = new ControlConnectionToTransport(
					Constants.CONTROL_PORT, this);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	@Override
	public void disconnected() {
		gui.resetConnectButtons();
		gui.out("Disconnected");

	}
	/**
	 * Returns true if the Chat is connected
	 * @return true if the Chat is connected, false if it is not
	 */
	public boolean isConnected() {
		return connected;
	}

	@Override
	public void connected() {
		if (!connected) {
			gui.out("chat.connected()");
			dataConnection = controlConnection.getDataConnection();
			in = new BufferedReader(new InputStreamReader(
					dataConnection.getInputStream()));
			out = new BufferedWriter(new OutputStreamWriter(
					dataConnection.getOutputStream()));
			connected = true;
			gui.connected();
			this.start();
		}
		// TODO Auto-generated method stub

	}

	/**
	 * Connects the application to another host
	 * 
	 * @param port
	 *            the port to connect to
	 * @param tpa
	 *            the address to connect to
	 */
	public void connect(int port, int tpa) {
		controlConnection.connect(port, tpa);
	}

	/**
	 * After calling this method the application will listen for an incoming
	 * connection on the given port
	 * 
	 * @param port
	 *            The port to listen to
	 */
	public void listen(int port) {
		controlConnection.listen(port);
	}

	/**
	 * Disconnects the other host
	 */
	public void disconnect() {
		controlConnection.disconnect();
		
		connected = false;
	}

	/**
	 * Formats the string into a string that is compatible to the protocol, then
	 * it sends that formatted string
	 * 
	 * @param msg
	 *            The message to send
	 */
	public void send(String msg) {
		ChatPacket packet = new ChatPacket(msg, this.name);
		toGui(packet.toString());
		try {
			out.write(packet.toString());
			out.flush();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	/**
	 * Reads incoming messages from the transport layer and sends them to the
	 * gui
	 */
	public void run() {
		while (connected) {
			try {
				try{
					String input = new String();
					for (int i = 0; i < 2; i++) {
						char last = (char) in.read();
						input += last;
						while (last != '\07') {
							last = (char) in.read();
							if (last != -1 ||last != 0){
								input += last;
							}

							while (last != '\07'){
								last = (char)in.read();
								if (last != -1||last != 0){
									input += last;
								}
							}
						}
					}
					toGui(input);
				} 
				catch(SocketException e){
					connected = false;
				}
			}
			catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
	/**
	 * Formats incoming messages to a readable format and sends them to the gui
	 * 
	 * @param msg
	 *            The incoming message
	 */
	public void toGui(String msg) {
		ChatPacket message = new ChatPacket(msg);
		String output = new String();
		Date date = new Date(message.getTimeStamp() * 1000);
		output += date.toString();
		output += " ";
		output += message.getName();
		output += ": ";
		output += message.getMessage();
		gui.out(output);
		
	}

}
